#ifndef OCR_H
#define OCR_H

#include "opencv/cv.h"
#include "ip.h"
#include <QString>
#include <QVector>
#include <QMap>

class TrainingPair
{
public:
  cv::Mat x;
  QString y;
  TrainingPair() {}
  TrainingPair(const cv::Mat& x_, const QString& y_)
  {
    x = x_.clone();
    y = y_;
  }
  const TrainingPair& operator =(const TrainingPair& p)
  {
    x = p.x.clone();
    y = p.y;
    return *this;
  }
};

class TrainingSet : public QVector<TrainingPair>
{

};

class ReducedFeature
{
public:
  double fg_faction;

  ReducedFeature() : fg_faction(0) {}
  ReducedFeature(const cv::Mat& x)
  {
    double n = x.rows * x.cols, s = 0;
    RGB bg(255, 255, 255);
    for (int i = 0; i < x.rows; i++)
      for (int j = 0; j < x.cols; j++)
        if (IP::getRGB(x, i, j) != bg) s += 1;
    fg_faction = floor(s / n * 1000) / 1000;
  }

  bool operator == (const ReducedFeature& f) const
  {
    return fg_faction == f.fg_faction;
  }
  bool operator < (const ReducedFeature& f) const
  {
    return fg_faction < f.fg_faction;
  }
};

class OCR
{
  TrainingSet m_ts;
  QMap<ReducedFeature, QVector<int> > m_map;
public:
  OCR();

  QString recognize(const cv::Mat& x);

  void save(const cv::Mat& x, const QString& y);
  void addTrainingPair(const cv::Mat& x, const QString& y);
  void loadCurrentSet();
  cv::Mat normalize(const cv::Mat& x);
  cv::Rect boundingBox(const cv::Mat& x);
  QString getNextFileName();
  void saveNextFileName(QString fn);
};

#endif // OCR_H
